package com.cupk.services;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cupk.dtos.*;
import com.cupk.entities.Funding;
import com.cupk.entities.Project;
import com.cupk.entities.User;
import com.cupk.exceptions.ResourceNotFoundException;
import com.cupk.mapper.FundingMapper;
import com.cupk.mapper.ProjectMapper;
import com.cupk.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class FundingService {

    private final FundingMapper fundingMapper;
    private final UserMapper userMapper;
    private final ProjectMapper projectMapper;

    /**
     * 创建经费记录
     */
    @Transactional
    public FundingDto createFunding(CreateFundingRequest request, String username) {
        User recorder = findUserByUsername(username);
        if (request.getProjectId() != null && projectMapper.selectById(request.getProjectId()) == null) {
            throw new ResourceNotFoundException("关联的项目未找到, ID: " + request.getProjectId());
        }

        Funding funding = new Funding();
        funding.setProjectId(request.getProjectId());
        funding.setFundingType(request.getFundingType());
        funding.setCategory(request.getCategory());
        funding.setAmount(request.getAmount());
        funding.setDescription(request.getDescription());
        funding.setTransactionDate(LocalDate.parse(request.getTransactionDate(), DateTimeFormatter.ISO_LOCAL_DATE));
        funding.setReceiptNumber(request.getReceiptNumber());
        funding.setRecordedById(recorder.getId());
        funding.setApprovalStatus("PENDING"); // 新建的记录默认为待审批

        fundingMapper.insert(funding);
        log.info("用户 {} 创建了新的经费记录, ID: {}", username, funding.getId());
        return convertToDto(funding);
    }

    /**
     * 更新经费记录
     */
    @Transactional
    public FundingDto updateFunding(Long id, UpdateFundingRequest request, String username) {
        Funding funding = findFundingById(id);
        User user = findUserByUsername(username);

        // 权限检查：只有记录人或管理员可以编辑
        if (!funding.getRecordedById().equals(user.getId()) && !"ADMIN".equals(user.getRole())) {
            throw new IllegalArgumentException("您没有权限编辑此经费记录");
        }

        // 只有待审批的记录可以被编辑
        if (!"PENDING".equals(funding.getApprovalStatus())) {
            throw new IllegalArgumentException("只有待审批状态的记录可以编辑");
        }

        if (request.getProjectId() != null) funding.setProjectId(request.getProjectId());
        if (request.getFundingType() != null) funding.setFundingType(request.getFundingType());
        if (request.getCategory() != null) funding.setCategory(request.getCategory());
        if (request.getAmount() != null) funding.setAmount(request.getAmount());
        if (request.getDescription() != null) funding.setDescription(request.getDescription());
        if (request.getTransactionDate() != null) funding.setTransactionDate(LocalDate.parse(request.getTransactionDate()));
        if (request.getReceiptNumber() != null) funding.setReceiptNumber(request.getReceiptNumber());

        fundingMapper.updateById(funding);
        log.info("用户 {} 更新了经费记录, ID: {}", username, id);
        return convertToDto(funding);
    }

    /**
     * 审批经费记录
     */
    @Transactional
    public FundingDto approveFunding(Long id, boolean approved, String approverUsername) {
        Funding funding = findFundingById(id);
        User approver = findUserByUsername(approverUsername);

        // 假设只有管理员有审批权限
        if (!"ADMIN".equals(approver.getRole())) {
            throw new IllegalArgumentException("您没有审批权限");
        }

        funding.setApprovalStatus(approved ? "APPROVED" : "REJECTED");
        funding.setApproverId(approver.getId());

        fundingMapper.updateById(funding);
        log.info("用户 {} 审批了经费记录, ID: {}, 结果: {}", approverUsername, id, funding.getApprovalStatus());
        return convertToDto(funding);
    }

    /**
     * 删除经费记录
     */
    @Transactional
    public void deleteFunding(Long id, String username) {
        Funding funding = findFundingById(id);
        User user = findUserByUsername(username);

        // 权限检查：只有记录人或管理员可以删除
        if (!funding.getRecordedById().equals(user.getId()) && !"ADMIN".equals(user.getRole())) {
            throw new IllegalArgumentException("您没有权限删除此经费记录");
        }

        if (fundingMapper.deleteById(id) > 0) {
            log.info("用户 {} 删除了经费记录, ID: {}", username, id);
        } else {
            // 如果能找到但删除失败，这里可以记录一个更具体的错误
            // 但通常情况下，找不到就会在 findFundingById 抛出异常
            log.warn("尝试删除经费记录失败，可能已被删除, ID: {}", id);
        }
    }

    /**
     * 根据筛选条件获取所有经费记录
     *
     * @param projectId       项目ID (可选)
     * @param fundingType     收支类型 (可选)
     * @param approvalStatus  审批状态 (可选)
     * @param startDate       开始日期字符串 (YYYY-MM-DD, 可选)
     * @param endDate         结束日期字符串 (YYYY-MM-DD, 可选)
     * @param keyword         搜索关键词 (可选)
     * @return 筛选后的经费记录列表
     */
    @Transactional(readOnly = true)
    public List<FundingDto> getAllFundings(Long projectId, String fundingType, String approvalStatus,
                                           String startDate, String endDate, String keyword) {

        QueryWrapper<Funding> queryWrapper = new QueryWrapper<>();

        // 1. 项目ID筛选
        if (projectId != null) {
            queryWrapper.eq("project_id", projectId);
        }

        // 2. 收支类型筛选
        if (fundingType != null && !fundingType.isEmpty()) {
            queryWrapper.eq("funding_type", fundingType);
        }

        // 3. 审批状态筛选
        if (approvalStatus != null && !approvalStatus.isEmpty()) {
            queryWrapper.eq("approval_status", approvalStatus);
        }

        // 4. 日期范围筛选
        if (startDate != null && !startDate.isEmpty()) {
            queryWrapper.ge("transaction_date", LocalDate.parse(startDate)); // ge = Greater than or Equal to
        }
        if (endDate != null && !endDate.isEmpty()) {
            queryWrapper.le("transaction_date", LocalDate.parse(endDate)); // le = Less than or Equal to
        }

        // 5. 关键词搜索 (模糊查询描述和票据号)
        if (keyword != null && !keyword.isEmpty()) {
            queryWrapper.and(wrapper -> wrapper.like("description", keyword)
                    .or()
                    .like("receipt_number", keyword));
        }

        // 按交易日期降序排序，最新的在前面
        queryWrapper.orderByDesc("transaction_date");

        return fundingMapper.selectList(queryWrapper).stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    /**
     * 根据项目ID获取经费记录
     */
    @Transactional(readOnly = true)
    public List<FundingDto> getFundingsByProject(Long projectId) {
        if (projectMapper.selectById(projectId) == null) {
            throw new ResourceNotFoundException("项目未找到, ID: " + projectId);
        }
        QueryWrapper<Funding> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", projectId);
        return fundingMapper.selectList(queryWrapper).stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    /**
     * 获取指定用户的经费记录
     */
    @Transactional(readOnly = true)
    public List<FundingDto> getUserFundings(String username) {
        User user = findUserByUsername(username);
        QueryWrapper<Funding> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("recorded_by_id", user.getId());
        return fundingMapper.selectList(queryWrapper).stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    /**
     * 获取经费统计信息
     */
    @Transactional(readOnly = true)
    public FundingStatsDto getFundingStats() {
        List<Funding> allFundings = fundingMapper.selectList(null);

        FundingStatsDto stats = new FundingStatsDto();

        BigDecimal totalIncome = allFundings.stream()
                .filter(f -> "INCOME".equals(f.getFundingType()) && "APPROVED".equals(f.getApprovalStatus()))
                .map(Funding::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal totalExpense = allFundings.stream()
                .filter(f -> "EXPENSE".equals(f.getFundingType()) && "APPROVED".equals(f.getApprovalStatus()))
                .map(Funding::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        stats.setTotalIncome(totalIncome);
        stats.setTotalExpense(totalExpense);
        stats.setBalance(totalIncome.subtract(totalExpense));

        stats.setPendingAmount(allFundings.stream()
                .filter(f -> "PENDING".equals(f.getApprovalStatus()))
                .map(Funding::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add));

        stats.setApprovedAmount(totalIncome.add(totalExpense));

        stats.setRejectedAmount(allFundings.stream()
                .filter(f -> "REJECTED".equals(f.getApprovalStatus()))
                .map(Funding::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add));

        // 月度和分类统计可以根据需要实现，目前返回空列表以匹配DTO结构
        stats.setMonthlyStats(List.of());
        stats.setCategoryStats(List.of());

        return stats;
    }


    // --- 辅助方法 ---

    private Funding findFundingById(Long id) {
        Funding funding = fundingMapper.selectById(id);
        if (funding == null) {
            throw new ResourceNotFoundException("经费记录未找到, ID: " + id);
        }
        return funding;
    }

    private User findUserByUsername(String username) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        if (user == null) {
            throw new ResourceNotFoundException("用户未找到: " + username);
        }
        return user;
    }

    private FundingDto convertToDto(Funding funding) {
        FundingDto dto = new FundingDto();
        dto.setId(funding.getId());
        dto.setProjectId(funding.getProjectId());
        dto.setFundingType(funding.getFundingType());
        dto.setCategory(funding.getCategory());
        dto.setAmount(funding.getAmount());
        dto.setDescription(funding.getDescription());
        dto.setTransactionDate(funding.getTransactionDate() != null ? funding.getTransactionDate().format(DateTimeFormatter.ISO_LOCAL_DATE) : null);
        dto.setApprovalStatus(funding.getApprovalStatus());
        dto.setReceiptNumber(funding.getReceiptNumber());

        if (funding.getCreatedAt() != null) {
            dto.setCreatedAt(funding.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }
        if (funding.getUpdatedAt() != null) {
            dto.setUpdatedAt(funding.getUpdatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        }

        // 填充关联的项目名称
        if (funding.getProjectId() != null) {
            Project project = projectMapper.selectById(funding.getProjectId());
            if (project != null) {
                dto.setProjectName(project.getProjectName());
            }
        }

        // 填充审批人姓名
        if (funding.getApproverId() != null) {
            User approver = userMapper.selectById(funding.getApproverId());
            if (approver != null) {
                dto.setApprovedBy(approver.getFullName() != null && !approver.getFullName().isEmpty() ? approver.getFullName() : approver.getUsername());
            }
        }

        // 附件逻辑可以根据 AttachmentService (如果存在) 来填充, 此处返回空列表
        dto.setAttachments(List.of());
        dto.setRecordedById(funding.getRecordedById());

        return dto;
    }
}